package com.teach.javafxclient.controller.base;

/**
 * @author Liang Jianlin
 * @date 2024-04-13 15:32
 */

import com.teach.javafxclient.Globalvar;
import com.teach.javafxclient.MainApplication;
import com.teach.javafxclient.util.HttpUtil;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TabPane;
import javafx.scene.image.Image;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.control.Button;
import javafx.scene.shape.Circle;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 使用链表来存储层级关系来渲染按钮
 */
public class StudentManageController {
    public HBox registerStudent;
    @FXML
    private VBox mainContent;
    @FXML
    private HBox pageRoot;
    private TabPane tabNode;
    private FXMLLoader tabLoader;
    private TabPaneController tabC;
    @FXML
    public FlowPane buttonView;
    @FXML
    public VBox subContent;
    @FXML
    private VBox showView;
    @FXML
    private Button headButton;
    public ButtonNode head;
    private Map<String, JSONArray> maps = new HashMap<>();
    ButtonLinkedList bl = new ButtonLinkedList();
    final Parent[] finalTaRoot = {null};

    public void initialize() throws IOException {
        JSONArray colleges = HttpUtil.get(Globalvar.baseUrl + "/api/colleges")
                .header("Content-Type", "application/json")
                .asJson().getBody().getArray();
        maps.put("山东大学", colleges);
        Button head = new Button("山东大学");
        head.setOnAction(e -> {
            showView.getChildren().clear();
            bl.deleteNextNode(head);
            bl.showInBlank(buttonView);
            try {
                setCollegesShowView(maps.get(bl.getLinkStr()));
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        });
        bl.add(head);
        bl.showInBlank(buttonView);
        setCollegesShowView(maps.get(bl.getLinkStr()));

        registerStudent.setOnMouseClicked(e->{
            if (subContent.getChildren().isEmpty()) {
                tabLoader = new FXMLLoader(MainApplication.class.getResource("base/tab-pane.fxml"));
                try {
                    tabNode = tabLoader.load();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
                ChangeListener<Number> widthListener;
                widthListener = (observable, oldValue, newValue) -> {
                    Double pageWidth = newValue.doubleValue();
                    System.out.println(pageWidth);
                    mainContent.setPrefWidth(pageWidth*0.52);
                    subContent.setPrefWidth(pageWidth * 0.40);
                };
                pageRoot.widthProperty().addListener(widthListener);
                tabC = tabLoader.getController();
                subContent.getChildren().add(tabNode);
            }
            FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("base/student-register.fxml"));
            Scene scene;
            try {
                Parent studentRegisterPage = fxmlLoader.load();
                scene = new Scene(studentRegisterPage);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            tabC.changeContentByScene(scene, "base/student-info","注册学生");
        });
    }

    private void addSort(String sortName, Integer sortId) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("base/sort.fxml"));
        Parent root = fxmlLoader.load();
        SortController sc = fxmlLoader.getController();
        sc.sort.setText(sortName);
        showView.getChildren().add(root);
        root.setOnMouseClicked(e -> {
            showView.getChildren().clear();
            System.out.println(sc.sort.getText());
            Button b1 = new Button('<' + sc.sort.getText());
            bl.add(b1);
            bl.showInBlank(buttonView);
            if (bl.length() != 2) {
                b1.setOnAction(e2 -> {
                    showView.getChildren().clear();
                    bl.deleteNextNode(b1);
                    bl.showInBlank(buttonView);
                    try {
                        setShowView(maps.get(bl.getLinkStr()));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                });
            }

            if (maps.get(bl.getLinkStr()) != null && bl.length() != 2) {
                try {
                    setShowView(maps.get(bl.getLinkStr()));
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            } else if (maps.get(bl.getLinkStr()) != null && bl.length() == 2) {
                showView.getChildren().add(finalTaRoot[0]);
                try {
                    setGradesShowView(maps.get(bl.getLinkStr()));
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            } else {
                if (bl.length() == 2) {
                    JSONObject response = HttpUtil.get(Globalvar.baseUrl + "/api/colleges/" + sortId)
                            .header("Accept", "application/json") // 设置请求头（如果需要的话）
                            .asJson().getBody().getObject();
                    maps.put(bl.getLinkStr(), (JSONArray) response.get("grades"));
                    System.out.println("response");

                    System.out.println(response);
                    FXMLLoader fxmlLoader1 = new FXMLLoader(MainApplication.class.getResource("base/teacher-and-admin.fxml"));
                    Parent taRoot = null;
                    try {
                        taRoot = fxmlLoader1.load();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                    TeacherAndAdminController tac = fxmlLoader1.getController();
                    JSONArray adminRes = HttpUtil.get(Globalvar.baseUrl + "/api/admins")
                            .header("Accept", "application/json") // 设置请求头（如果需要的话）
                            .asJson().getBody().getArray();
                    maps.put(bl.getLinkStr(), (JSONArray) response.get("grades"));
                    System.out.println("response");
                    tac.adminNum.setText(String.valueOf(adminRes.length()));
                    tac.teacherNum.setText(String.valueOf(((JSONArray) response.get("teachers")).length()));
                    JSONArray teachers = (JSONArray) response.get("teachers");
                    JSONArray admins = adminRes;
                    System.out.println(admins);
                    tac.adminContainer.setOnMouseClicked(e1 -> {
                        System.out.println(admins);
                        showView.getChildren().clear();
                        Button b2 = new Button("<管理员");
                        bl.add(b2);
                        bl.showInBlank(buttonView);
                        b2.setOnAction(e2 -> {
                            showView.getChildren().clear();
                            bl.deleteNextNode(b2);
                            bl.showInBlank(buttonView);
                            for (int i = 0; i < admins.length(); i++) {
                                try {
                                    addTeacherAndAdmin(String.valueOf(((JSONObject) admins.get(i)).get("specificId")), (String) ((JSONObject) admins.get(i)).get("name"),false);
                                } catch (IOException ex) {
                                    throw new RuntimeException(ex);
                                }
                            }

                        });
                        for (int i = 0; i < admins.length(); i++) {
                            try {
                                addTeacherAndAdmin(String.valueOf(((JSONObject) admins.get(i)).get("specificId")), (String) ((JSONObject) admins.get(i)).get("name"),false);
                            } catch (IOException ex) {
                                throw new RuntimeException(ex);
                            }
                        }
                    });
                    tac.teacherContainer.setOnMouseClicked(e1 -> {
                        showView.getChildren().clear();
                        Button b2 = new Button("<教师");
                        bl.add(b2);
                        bl.showInBlank(buttonView);
                        b2.setOnAction(e2 -> {
                            showView.getChildren().clear();
                            bl.deleteNextNode(b2);
                            bl.showInBlank(buttonView);

                            for (int i = 0; i < teachers.length(); i++) {
                                try {
                                    addTeacherAndAdmin(String.valueOf(((JSONObject) teachers.get(i)).get("id")), (String) ((JSONObject) teachers.get(i)).get("name"),true);
                                } catch (IOException ex) {
                                    throw new RuntimeException(ex);
                                }
                            }

                        });
                        for (int i = 0; i < teachers.length(); i++) {
                            try {
                                addTeacherAndAdmin(String.valueOf(((JSONObject) teachers.get(i)).get("id")), (String) ((JSONObject) teachers.get(i)).get("name"),true);
                            } catch (IOException ex) {
                                throw new RuntimeException(ex);
                            }
                        }
                    });
                    showView.getChildren().add(taRoot);


                    finalTaRoot[0] = taRoot;
                    b1.setOnAction(e2 -> {
                        showView.getChildren().clear();
                        bl.deleteNextNode(b1);
                        bl.showInBlank(buttonView);
                        showView.getChildren().add(finalTaRoot[0]);
                        try {
                            setGradesShowView(maps.get(bl.getLinkStr()));
                        } catch (IOException ex) {
                            throw new RuntimeException(ex);
                        }
                    });
                    try {
                        setGradesShowView(maps.get(bl.getLinkStr()));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                } else if (bl.length() == 3) {
                    System.out.println("update maps");
                    JsonNode response = HttpUtil.get(Globalvar.baseUrl + "/api/grades/" + sortId + "/classes")
                            .header("Accept", "application/json") // 设置请求头（如果需要的话）
                            .asJson().getBody();
                    maps.put(bl.getLinkStr(), response.getArray());
                    try {
                        setShowView(maps.get(bl.getLinkStr()));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                } else if (bl.length() == 4) {
                    System.out.println("update maps");
                    JsonNode response = HttpUtil.get(Globalvar.baseUrl + "/api/classes/" + sortId + "/students")
                            .header("Accept", "application/json") // 设置请求头（如果需要的话）
                            .asJson().getBody();
                    maps.put(bl.getLinkStr(), response.getArray());
                    try {
                        setShowView(maps.get(bl.getLinkStr()));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                }
            }
        });
    }

    private void addStudent(String name, String job, Long id, String gender) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("base/student-item.fxml"));
        Parent root = fxmlLoader.load();
        StudentItemController sc = fxmlLoader.getController();
        job = (job == null ? "" : job);
        Map<String, String> genderMap = new HashMap<>();
        genderMap.put("male", "男");
        genderMap.put("female", "女");
        gender = genderMap.get(gender);
        sc.name.setText(name);
        sc.job.setText(job);
        sc.id.setText(String.valueOf(id));
        sc.gender.setText(gender);
        System.out.println("准备发请求");
        HttpResponse avatarRes = HttpUtil.get(Globalvar.baseUrl + "/api/users/" + id + "/avatar")
                .header("Accept", "application/json") // 设置请求头（如果需要的话）
                .asBytes();
        System.out.println("收到响应");
        Image img;
        if(avatarRes.getStatus() != 200){
            img = new Image(getClass().getResource("/com/teach/javafxclient/picture/用户-圆.png").toExternalForm());
        }else{
            img = new Image(new ByteArrayInputStream((byte[]) avatarRes.getBody()));
        }
        double wid = Math.min(img.getWidth() , img.getHeight());
        Circle clip = new Circle(sc.avatar.getFitWidth() / 2, sc.avatar.getFitHeight() / 2, Math.min(sc.avatar.getFitWidth() , sc.avatar.getFitHeight()) / 2);
        sc.avatar.setClip(clip);
        Rectangle2D viewport = new Rectangle2D(img.getWidth()/2 - wid/2, img.getHeight()/2 - wid/2, wid, wid);
        sc.avatar.setViewport(viewport);
        sc.avatar.setImage(img);

        showView.getChildren().add(root);
        root.setOnMouseClicked(e -> {
            if (subContent.getChildren().isEmpty()) {
                tabLoader = new FXMLLoader(MainApplication.class.getResource("base/tab-pane.fxml"));
                try {
                    tabNode = tabLoader.load();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
                ChangeListener<Number> widthListener;
                widthListener = (observable, oldValue, newValue) -> {
                    Double pageWidth = newValue.doubleValue();
                    System.out.println(pageWidth);
//                    mainContent.setPrefWidth(pageWidth*0.52);
                    subContent.setPrefWidth(pageWidth * 0.30);
                };
                pageRoot.widthProperty().addListener(widthListener);
                tabC = tabLoader.getController();
                subContent.getChildren().add(tabNode);
            }
            FXMLLoader fxmlLoader2 = new FXMLLoader(MainApplication.class.getResource("base/student-info.fxml"));
            Scene scene;
            try {
                Parent studentPage = fxmlLoader2.load();
                StudentInfoController stuInfoC = fxmlLoader2.getController();
                stuInfoC.setStudentInfo(String.valueOf(id));
                scene = new Scene(studentPage);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            tabC.changeContentByScene(scene, "base/student-info", name);
        });
    }


    private void addTeacherAndAdmin(String id, String name,Boolean isTeacher) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("base/student-item.fxml"));
        Parent root = fxmlLoader.load();
        System.out.println("准备发请求");
        HttpResponse avatarRes = Unirest.get(Globalvar.baseUrl + "/api/users/" + id + "/avatar")
                .header("Accept", "application/json") // 设置请求头（如果需要的话）
                .asBytes();
        StudentItemController sc = fxmlLoader.getController();
        System.out.println("收到响应了");
        Image img;
        if(avatarRes.getStatus() == 404){
            img = new Image(getClass().getResource("/com/teach/javafxclient/picture/用户-圆.png").toExternalForm());
        }else{
            img = new Image(new ByteArrayInputStream((byte[]) avatarRes.getBody()));
        }
        double wid = Math.min(img.getWidth() , img.getHeight());
        Circle clip = new Circle(sc.avatar.getFitWidth() / 2, sc.avatar.getFitHeight() / 2, Math.min(sc.avatar.getFitWidth() , sc.avatar.getFitHeight()) / 2);
        sc.avatar.setClip(clip);
        Rectangle2D viewport = new Rectangle2D(img.getWidth()/2 - wid/2, img.getHeight()/2 - wid/2, wid, wid);
        sc.avatar.setViewport(viewport);
        sc.avatar.setImage(img);
        sc.name.setText(name);
        sc.job.setText("");
        sc.id.setText(id);
        showView.getChildren().add(root);
        System.out.println("在加了，真在加了");
        if (isTeacher){
            root.setOnMouseClicked(e -> {
                if (subContent.getChildren().isEmpty()) {
                    tabLoader = new FXMLLoader(MainApplication.class.getResource("base/tab-pane.fxml"));
                    try {
                        tabNode = tabLoader.load();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                    ChangeListener<Number> widthListener;
                    widthListener = (observable, oldValue, newValue) -> {
                        Double pageWidth = newValue.doubleValue();
                        System.out.println(pageWidth);
//                    mainContent.setPrefWidth(pageWidth*0.52);
                        subContent.setPrefWidth(pageWidth * 0.30);
                    };
                    pageRoot.widthProperty().addListener(widthListener);
                    tabC = tabLoader.getController();
                    subContent.getChildren().add(tabNode);
                }
                FXMLLoader fxmlLoader2 = new FXMLLoader(MainApplication.class.getResource("base/student-info.fxml"));
                Scene scene;
                try {
                    Parent teacherPage = fxmlLoader2.load();
                    StudentInfoController stuInfoC = fxmlLoader2.getController();
                    stuInfoC.setTeacherInfo(id);
                    scene = new Scene(teacherPage);
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
                tabC.changeContentByScene(scene, "base/student-info", name);
            });
        }
    }

    private void setShowView(JSONArray ja) throws IOException {
        if (((JSONObject) ja.get(0)).has("classId")) {
            System.out.println("show ok");
            for (int i = 0; i < ja.length(); i++) {
                addSort((String) ((JSONObject) ja.get(i)).get("className"), (Integer) ((JSONObject) ja.get(i)).get("classId"));
            }
        }
        else {
            for (int i = 0; i < ja.length(); i++) {
                addStudent((String) ((JSONObject) ja.get(i)).get("name"), "", (Long) ((JSONObject) ja.get(i)).get("studentId"), (String) ((JSONObject) ja.get(i)).get("gender"));
            }
        }
    }

    private void setGradesShowView(JSONArray ja) throws IOException {
        if (((JSONObject) ja.get(0)).has("gradeId")) {
            System.out.println("show ok");
            for (int i = 0; i < ja.length(); i++) {
                addSort((String) ((JSONObject) ja.get(i)).get("gradeName"), (Integer) ((JSONObject) ja.get(i)).get("gradeId"));
            }
        }
        else {
            System.out.println("error");
        }
    }

    private void setCollegesShowView(JSONArray ja) throws IOException {
        if (((JSONObject) ja.get(0)).has("collegeId")) {
            System.out.println("show ok");
            for (int i = 0; i < ja.length(); i++) {
                addSort((String) ((JSONObject) ja.get(i)).get("collegeName"), (Integer) ((JSONObject) ja.get(i)).get("collegeId"));
            }
        }
        else {
            System.out.println("error");
        }
    }
}

class ButtonNode {
    public Button data;
    public ButtonNode next;

    ButtonNode(Button data) {
        this.data = data;
        this.next = null;
    }

    ButtonNode() {
        this.data = null;
        this.next = null;
    }
}

class ButtonLinkedList {
    private ButtonNode head; // 链表的头节点

    public ButtonLinkedList() {
        head = null; // 初始化一个空的链表
    }

    // 在链表末尾添加节点
    public void add(Button button) {
        System.out.println("add ok");
        ButtonNode newNode = new ButtonNode(button);
        if (head == null) {
            head = newNode;
        } else {
            ButtonNode current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
        System.out.println(head.data.getText());
    }

    // 在链表开头添加节点
    public void addAtStart(Button button) {
        ButtonNode newNode = new ButtonNode(button);
        newNode.next = head;
        head = newNode;
    }

    // 删除指定节点之后的节点
    public void deleteNextNode(Button targetData) {
        if (head == null) {
            // 链表为空，无法删除
            return;
        }

        ButtonNode current = head;
        // 寻找数据为 targetData 的节点
        while (current != null && current.data.getText() != targetData.getText()) {
            current = current.next;
        }

        if (current == null) {
            System.out.println("没有");
            return;
        }

        if (current.next != null) {
            System.out.println("delete ok");
            // 删除目标节点之后的节点
            current.next = null; // 帮助垃圾回收
        } else {
            // 目标节点已经是链表的最后一个节点，没有节点可删除
        }
    }

    public void showInBlank(FlowPane buttonView) {
        ButtonNode current = head;
        ButtonNode pre = new ButtonNode();
        System.out.println(head.data.getText());
        buttonView.getChildren().clear();
        while (current != null) {
            if (pre.data != null) {
                pre.data.setStyle("-fx-text-fill: #707070");
            }
            System.out.println("input ok");
            current.data.setStyle("-fx-text-fill: black");
            buttonView.getChildren().add(current.data);
            pre = current;
            current = current.next;
        }
    }

    public String getLinkStr() {
        ButtonNode current = head;
        String str = new String();
        while (current != null) {
            str += current.data.getText();
            current = current.next;
        }
        System.out.println(str);
        return str;
    }

    public Integer length() {
        ButtonNode current = head;
        Integer count = 0;
        while (current != null) {
            current = current.next;
            count++;
        }
        return count;
    }
}
